package com.yjd.comm.fs.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import javax.activation.MimetypesFileTypeMap;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;

import com.yjd.comm.fs.model.FileUploadedModel;
import com.yjd.comm.fs.model.FsFtpModel;
import com.yjd.comm.util.FrameUtil;

public class FtpAllUtil {
	private static Logger logger = Logger.getLogger(FtpAllUtil.class);
	/**
	 * @Title: connectionFtp
	 * @Description: 链接ftp
	 * @param @param ftpModel
	 * @param @return 设定文件
	 * @return FtpClient 返回类型
	 * @throws
	 */
	public static FTPClient getFtpConn(FsFtpModel fsFtpModel) {
		FTPClient ftpClient = null;
		try {
			/* ******连接服务器的两种方法****** */
			ftpClient = new FTPClient();
			ftpClient.connect(fsFtpModel.getIp(), fsFtpModel.getPort());
			ftpClient.login(fsFtpModel.getUsername(), fsFtpModel.getPassword());
			ftpClient.setControlEncoding(fsFtpModel.getDefaultEncoding());
			// 设置成2进制传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

			int reply = ftpClient.getReplyCode();
			ftpClient.setDataTimeout(120000);

			if (!FTPReply.isPositiveCompletion(reply)) {
				ftpClient.disconnect();
				logger.info("FTP server refused connection.");
			}
			//设置缓存区大小为10mb，不然上传速度是蜗牛速度啊
			ftpClient.setBufferSize(1024 * 1024 * 10);
			logger.info("FTP登入成功login success!");
		} catch (Exception e) {
			logger.error("链接FTP出错");
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
		return ftpClient;
	}

	/**
	 * 关闭连接
	 * 
	 * @date 2012-7-11
	 */
	public static void closeFtpConn(FTPClient ftpClient) {
		try {
			if (ftpClient != null) {
				ftpClient.logout();
				ftpClient.disconnect();
				logger.info("FTP注销成功loginout success!");
			}
		} catch (IOException ex) {
			logger.error("断开连接失败");
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}

	/**
	 * 上传单个文件，并重命名
	 * 
	 * @param localFile
	 *            --本地文件路径
	 * @param distFolder
	 *            --新的文件名,可以命名为空""
	 * @return true 上传成功，false 上传失败
	 */
	public static boolean upload(FsFtpModel fsFtpModel, String localFileStr,
			String remotefile) {
		boolean flag = true;
		FTPClient ftpClient = null;
		try {
			ftpClient = getFtpConn(fsFtpModel);
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			ftpClient.enterLocalPassiveMode();
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);

			String charsetName = "GBK";
			if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
					"OPTS UTF8", "ON"))) // 发送OPTS UTF8指令，尝试支持utf-8
				charsetName = "utf-8";
			remotefile = new String(remotefile.getBytes(charsetName),
					"ISO-8859-1");
			File localFile = new File(localFileStr);
			InputStream input = new FileInputStream(localFile);

			File ftpfile = new File(remotefile);
			createDirecroty(ftpClient, ftpfile.getParent());

			flag = ftpClient.storeFile(remotefile, input);
			if (flag) {
				logger.info("上传文件成功！");
			} else {
				logger.info("上传文件失败！");
			}
			input.close();
		} catch (Exception e) {
			logger.error("本地文件上传失败！");
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			try {
				closeFtpConn(ftpClient);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				throw new RuntimeException(e);
			}
		}
		return flag;
	}

	
	/**
	 * 通过File上传单个文件，并重命名
	 * 
	 * @param localFile
	 *            --本地文件路径
	 * @param remotefile
	 *            --远程路径
	 * @return FileUploadedModel 上传后的文件信息
	 */
	public static FileUploadedModel uploadFileItem( File localFile,
			String remotefile) {
		long startime = System.currentTimeMillis();
		boolean flag = true;
		FsFtpModel fsFtpModel=getFsFtpModelForUpload();
		FileUploadedModel fum=null;
		FTPClient ftpClient = null;
		try {
			ftpClient = getFtpConn(fsFtpModel);
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			ftpClient.enterLocalPassiveMode();
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
			String ext=remotefile.substring(remotefile.lastIndexOf(".")+1);
			String charsetName = "GBK";
			if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
					"OPTS UTF8", "ON"))) // 发送OPTS UTF8指令，尝试支持utf-8
				charsetName = "utf-8";
			remotefile = new String(remotefile.getBytes(charsetName),
					"utf-8");
			InputStream input = new FileInputStream(localFile);

			File ftpfile = new File(remotefile);
			ftpClient.makeDirectory(ftpfile.getParent().toString());
			createDirecroty(ftpClient, ftpfile.getParent());
			flag = ftpClient.storeFile(remotefile, input);
			if (flag) {
				fum=new FileUploadedModel();
				fum.setAttachment(remotefile);
				fum.setAttachurl(remotefile);
				fum.setId(remotefile.substring(0, remotefile.lastIndexOf(".")));
				fum.setSize(localFile.length());
				fum.setExt(ext);
				fum.setTemp_name(localFile.getName());
				fum.setType(new MimetypesFileTypeMap().getContentType(localFile));
				logger.info("上传文件成功！");
			} else {
				logger.info("上传文件失败！");
			}
			input.close();
		} catch (Exception e) {
			logger.error("本地文件上传失败！");
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			try {
				closeFtpConn(ftpClient);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				throw new RuntimeException(e);
			}
		}
		logger.info("耗时(ms)==========================="+(System.currentTimeMillis()-startime));
		return fum;
	}
	
	
	/**
	 * 通过File上传单个文件，并重命名
	 * 
	 * @param localFile
	 *            --本地文件路径
	 * @param remotefile
	 *            --远程路径
	 * @return FileUploadedModel 上传后的文件信息
	 */
	public static FileUploadedModel uploadFileItem(MultipartFile localFile,
			String remotefile) {
		return uploadFileItem(localFile,remotefile,getFsFtpModelForUpload());
	}
	
	/**
	 * 上传apk文件
	 * 
	 * @param localFile
	 *            --本地文件路径
	 * @param remotefile
	 *            --远程路径
	 * @return FileUploadedModel 上传后的文件信息
	 */
	public static FileUploadedModel ApkUploadFileItem(MultipartFile localFile,
			String remotefile) {
		return uploadFileItem(localFile,remotefile,getFsFtpApkModelForUpload());
	}
	
	
	public static FileUploadedModel uploadFileItem(MultipartFile localFile,String remotefile,FsFtpModel fsFtpModel){
		long startime = System.currentTimeMillis();
		boolean flag = true;
		FileUploadedModel fum=null;
		FTPClient ftpClient = null;
		try {
			ftpClient = getFtpConn(fsFtpModel);
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			ftpClient.enterLocalPassiveMode();
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
			String ext=remotefile.substring(remotefile.lastIndexOf(".")+1);
			String charsetName = "GBK";
			if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
					"OPTS UTF8", "ON"))) // 发送OPTS UTF8指令，尝试支持utf-8
				charsetName = "utf-8";
			remotefile = new String(remotefile.getBytes(charsetName),
					"utf-8");
			InputStream input = localFile.getInputStream();

			File ftpfile = new File(remotefile);
			ftpClient.makeDirectory(ftpfile.getParent().toString());
			createDirecroty(ftpClient, ftpfile.getParent());
			flag = ftpClient.storeFile(remotefile, input);
			if (flag) {
				fum=new FileUploadedModel();
				fum.setAttachment(remotefile);
				fum.setAttachurl(remotefile);
				fum.setId(remotefile.substring(0, remotefile.lastIndexOf(".")));
				fum.setSize(localFile.getSize());
				fum.setExt(ext);
				fum.setTemp_name(localFile.getOriginalFilename());
				fum.setType(new MimetypesFileTypeMap().getContentType(localFile.getContentType()));
				logger.info("上传文件成功！");
			} else {
				logger.info("上传文件失败！");
			}
			input.close();
		} catch (Exception e) {
			logger.error("本地文件上传失败！");
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			try {
				closeFtpConn(ftpClient);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				throw new RuntimeException(e);
			}
		}
		logger.info("耗时(ms)==========================="+(System.currentTimeMillis()-startime));
		return fum;
	}
	
	/**
	 * 递归创建远程服务器目录
	 * 
	 * @param remote
	 *            远程服务器文件绝对路径
	 * @param ftpClient
	 *            FTPClient对象
	 * @return 目录创建是否成功
	 * @throws IOException
	 */
	private static boolean createDirecroty(FTPClient ftpClient, String remote)
			throws IOException {
		String lineSeparator = File.separator;
		if (remote.startsWith(lineSeparator)) {
			remote = remote.substring(1);
		}
		if (remote.endsWith(lineSeparator)) {
			remote = remote.substring(0, remote.length() - 1);
		}
		String dirs[] = remote
				.split(lineSeparator.equalsIgnoreCase("\\") ? "\\\\"
						: lineSeparator);
		for (String dir : dirs) {
			if (ftpClient.changeWorkingDirectory(dir)) {
				continue;
			} else {
				ftpClient.makeDirectory(dir);
				ftpClient.changeWorkingDirectory(dir);
			}
		}
		return true;
	}
	/**
	 * 下载文件
	 * 
	 * @param remoteFileName
	 *            --服务器上的文件名
	 * @param localFileName
	 *            --本地文件名
	 * @return true 下载成功，false 下载失败
	 */
	public static boolean download(FsFtpModel fsFtpModel,
			String remoteFileName, String localFileName) {
		boolean flag = true;
		// 下载文件
		BufferedOutputStream buffOut = null;
		FTPClient ftpClient = null;
		try {
			ftpClient = getFtpConn(fsFtpModel);
			String charsetName = "GBK";
			if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
					"OPTS UTF8", "ON"))) // 发送OPTS UTF8指令，尝试支持utf-8
				charsetName = "utf-8";
			remoteFileName = new String(remoteFileName.getBytes(charsetName),
					"ISO-8859-1");

			File file_in = new File(localFileName);
			if (file_in.exists()) {
				file_in.delete();
			}

			File dir = new File(file_in.getParent());
			if (!dir.exists()) {
				dir.mkdir();
			}

			buffOut = new BufferedOutputStream(new FileOutputStream(
					localFileName));
			flag = ftpClient.retrieveFile(remoteFileName, buffOut);
			if (flag) {
				logger.info("本地文件下载成功");
			}
		} catch (Exception e) {
			logger.error("本地文件下载失败");
			logger.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} finally {
			try {
				if (buffOut != null) {
					buffOut.close();
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				throw new RuntimeException(e);
			}
		}
		return flag;
	}

	public static void main(String[] agrs) throws NumberFormatException, Exception {
//		FtpAllUtil fau=new FtpAllUtil();
		System.out.println("fsd");
		uploadTest();
	}

	private static void uploadTest() throws FileNotFoundException {
		for (int i = 0; i < 1; i++) {
			long starttime = System.currentTimeMillis();
			File file = new File("E:/软件/apache-maven-3.0.5.rar");
			FtpAllUtil.upload(getFsFtpModel(), "E:/软件/apache-maven-3.0.5.rar",
					"/ftp2/1/2" + UUID.randomUUID().toString() + ".rar");
			System.out.println(System.currentTimeMillis() - starttime);
		}
	}

	private static void downTest() {
		String filepath[] = { "/ftp1/getPinyin.sql", "/ftp1/yjd_web_menu.sql" };
		String localfilepath[] = { "C:\\temp\\1.sql", "D:\\temp\\2.sql" };

		for (int i = 0; i < 100; i++) {
			String localFile = "E:/fs/" + UUID.randomUUID().toString() + ".sql";
			long starttime = System.currentTimeMillis();
			FtpAllUtil.download(getFsFtpModel(), "/ftp2/yjd_web_menu.sql",
					localFile);
			System.out.println(System.currentTimeMillis() - starttime);
		}
	}

	private static FsFtpModel getFsFtpModel() {
		FsFtpModel fsFtpModel = new FsFtpModel();
		fsFtpModel.setIp("192.168.10.110");
		fsFtpModel.setPort(21);
		fsFtpModel.setUsername("likun");
		fsFtpModel.setPassword("111111");
		return fsFtpModel;
	}
	
	public static FsFtpModel getFsFtpModelForUpload() {
		FsFtpModel fsFtpModel = new FsFtpModel();
		fsFtpModel.setIp(FrameUtil.getConstResource("FTP.ip"));
		FrameUtil.getConstResource("FTP.port");
		fsFtpModel.setPort(Integer.parseInt(FrameUtil.getConstResource("FTP.port")));
		fsFtpModel.setUsername(FrameUtil.getConstResource("FTP.username"));
		fsFtpModel.setPassword(FrameUtil.getConstResource("FTP.password"));
		return fsFtpModel;
	}
	
	public static FsFtpModel getFsFtpApkModelForUpload() {
		FsFtpModel fsFtpModel = new FsFtpModel();
		fsFtpModel.setIp(FrameUtil.getConstResource("FTP.apk.ip"));
		FrameUtil.getConstResource("FTP.apk.port");
		fsFtpModel.setPort(Integer.parseInt(FrameUtil.getConstResource("FTP.apk.port")));
		fsFtpModel.setUsername(FrameUtil.getConstResource("FTP.apk.username"));
		fsFtpModel.setPassword(FrameUtil.getConstResource("FTP.apk.password"));
		return fsFtpModel;
	}
	
	private static void test(){
		uploadFileItem(new File("D:\\test.jpg"),"test.test");
	}
	
}